package org.dxy.trigger.http.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dxy.api.dto.request.substitute.*;
import org.dxy.api.dto.response.R;
import org.dxy.domain.command.substitute.*;
import org.dxy.domain.handler.substitute.*;
import org.dxy.infrastructure.persistent.po.query.SubstituteMaterialViewPo;
import org.dxy.infrastructure.persistent.service.SubstituteMaterialViewService;
import org.dxy.trigger.http.service.SubstituteMaterialApplicationService;
import org.dxy.types.common.CommandResult;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 替代料应用服务实现
 * @author dxy
 * @createTime 2025/9/13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SubstituteMaterialApplicationServiceImpl implements SubstituteMaterialApplicationService {
    
    // Command Handlers (写操作)
    private final AddSubstituteMaterialCommandHandler addSubstituteMaterialCommandHandler;
    private final UpdateSubstituteMaterialCommandHandler updateSubstituteMaterialCommandHandler;
    private final RemoveSubstituteMaterialCommandHandler removeSubstituteMaterialCommandHandler;
    private final ApproveSubstituteMaterialCommandHandler approveSubstituteMaterialCommandHandler;
    private final RejectSubstituteMaterialCommandHandler rejectSubstituteMaterialCommandHandler;
    private final ApplySubstituteMaterialToWorkOrderCommandHandler applySubstituteMaterialToWorkOrderCommandHandler;
    
    // Query Service (读操作)
    private final SubstituteMaterialViewService substituteMaterialViewService;
    
    @Override
    public R<Void> add(AddSubstituteMaterialRequest request) {
        try {
            log.info("添加替代料, request={}", request);
            
            AddSubstituteMaterialCommand command = new AddSubstituteMaterialCommand(
                    request.getMbomItemId(),
                    request.getSubstituteMaterialId(),
                    request.getSubstituteRatio(),
                    request.getPriority(),
                    request.getValidFrom(),
                    request.getValidTo());
            
            CommandResult<Void> result = addSubstituteMaterialCommandHandler.handle(command);
            
            if (result.success()) {
                return R.ok(null, result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("添加替代料失败", e);
            return R.fail("添加替代料失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> update(Long id, UpdateSubstituteMaterialRequest request) {
        try {
            log.info("更新替代料, id={}, request={}", id, request);
            
            UpdateSubstituteMaterialCommand command = new UpdateSubstituteMaterialCommand(
                    id,
                    request.getSubstituteRatio(),
                    request.getPriority(),
                    request.getValidFrom(),
                    request.getValidTo());
            
            CommandResult<Void> result = updateSubstituteMaterialCommandHandler.handle(command);
            
            if (result.success()) {
                return R.ok(null, result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("更新替代料失败", e);
            return R.fail("更新替代料失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> remove(Long id) {
        try {
            log.info("移除替代料, id={}", id);
            
            RemoveSubstituteMaterialCommand command = new RemoveSubstituteMaterialCommand(id);
            
            CommandResult<Void> result = removeSubstituteMaterialCommandHandler.handle(command);
            
            if (result.success()) {
                return R.ok(null, result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("移除替代料失败", e);
            return R.fail("移除替代料失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> approve(Long id) {
        try {
            log.info("审核通过替代料, id={}", id);
            
            ApproveSubstituteMaterialCommand command = new ApproveSubstituteMaterialCommand(id);
            
            CommandResult<Void> result = approveSubstituteMaterialCommandHandler.handle(command);
            
            if (result.success()) {
                return R.ok(null, result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("审核通过替代料失败", e);
            return R.fail("审核通过替代料失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> reject(Long id, RejectSubstituteMaterialRequest request) {
        try {
            log.info("审核拒绝替代料, id={}, request={}", id, request);
            
            RejectSubstituteMaterialCommand command = new RejectSubstituteMaterialCommand(
                    id, request.getRejectReason());
            
            CommandResult<Void> result = rejectSubstituteMaterialCommandHandler.handle(command);
            
            if (result.success()) {
                return R.ok(null, result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("审核拒绝替代料失败", e);
            return R.fail("审核拒绝替代料失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> applyToWorkOrder(Long id, ApplySubstituteMaterialToWorkOrderRequest request) {
        try {
            log.info("工单应用替代料, id={}, request={}", id, request);
            
            ApplySubstituteMaterialToWorkOrderCommand command = new ApplySubstituteMaterialToWorkOrderCommand(
                    id, request.getWorkOrderId(), request.getActualQuantity());
            
            CommandResult<Void> result = applySubstituteMaterialToWorkOrderCommandHandler.handle(command);
            
            if (result.success()) {
                return R.ok(null, result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("工单应用替代料失败", e);
            return R.fail("工单应用替代料失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Page<SubstituteMaterialViewPo>> list(Page<SubstituteMaterialViewPo> page, SubstituteMaterialViewPo query) {
        log.info("分页查询替代料列表, page={}, query={}", page, query);
        
        try {
            Page<SubstituteMaterialViewPo> result = substituteMaterialViewService.list(page, query);
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询替代料列表失败", e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<SubstituteMaterialViewPo> getById(Long id) {
        log.info("根据ID查询替代料详情, id={}", id);
        
        try {
            SubstituteMaterialViewPo result = substituteMaterialViewService.getById(id);
            if (result != null) {
                return R.ok(result, "查询成功");
            } else {
                return R.fail("替代料不存在");
            }
        } catch (Exception e) {
            log.error("查询替代料详情失败", e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<List<SubstituteMaterialViewPo>> getByMbomId(Long mbomId) {
        log.info("根据MBOM ID查询替代料列表, mbomId={}", mbomId);
        
        try {
            List<SubstituteMaterialViewPo> result = substituteMaterialViewService.getByMbomId(mbomId);
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询替代料列表失败", e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<List<SubstituteMaterialViewPo>> getByMbomItemId(Long mbomItemId) {
        log.info("根据MBOM项ID查询替代料列表, mbomItemId={}", mbomItemId);
        
        try {
            List<SubstituteMaterialViewPo> result = substituteMaterialViewService.getByMbomItemId(mbomItemId);
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询替代料列表失败", e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<List<SubstituteMaterialViewPo>> getByStatus(String status) {
        log.info("根据状态查询替代料列表, status={}", status);
        
        try {
            List<SubstituteMaterialViewPo> result = substituteMaterialViewService.getByStatus(status);
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询替代料列表失败", e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<List<SubstituteMaterialViewPo>> getByMainMaterialCode(String mainMaterialCode) {
        log.info("根据主料编码查询替代料列表, mainMaterialCode={}", mainMaterialCode);
        
        try {
            List<SubstituteMaterialViewPo> result = substituteMaterialViewService.getByMainMaterialCode(mainMaterialCode);
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询替代料列表失败", e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<List<SubstituteMaterialViewPo>> getBySubstituteMaterialCode(String substituteMaterialCode) {
        log.info("根据替代料编码查询替代料列表, substituteMaterialCode={}", substituteMaterialCode);
        
        try {
            List<SubstituteMaterialViewPo> result = substituteMaterialViewService.getBySubstituteMaterialCode(substituteMaterialCode);
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询替代料列表失败", e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<List<SubstituteMaterialViewPo>> getAvailableSubstitutes(Long mbomItemId) {
        log.info("查询可用的替代料, mbomItemId={}", mbomItemId);
        
        try {
            List<SubstituteMaterialViewPo> result = substituteMaterialViewService.getAvailableSubstitutes(mbomItemId);
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询可用替代料失败", e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }
}